import mx.utils.Delegate;

import gugga.common.EventDescriptor;
import gugga.common.ITask;
import gugga.navigation.NavigationButton;
import gugga.sequence.ExecuteMethodTask;
import gugga.sequence.TaskManager;
import gugga.sequence.TaskSequence;

import useOfSequences.CommonSection;

/** 
 * @author bony
 * In this section the sequences can be interrupted.
 * Can start the new sequence while the previous is running. 
 */
class useOfSequences.InterruptibleSection extends CommonSection 
{
	// CurrentSequence reference as ITask, because we want to use it for 
	// TaskSequence and TaskManager. Both of them implement the ITask interface.
	private var mCurrentSequence : ITask;
	
	private var mLinearSequenceButton: NavigationButton;
	private var mBackwardsButton: NavigationButton;
	private var mComplexSequenceButton: NavigationButton;
	private var mZigZagSequenceButton: NavigationButton;
	
	// Those tasks will be included in appropriate place in all sequences. 
	private var mEnableSequencesNavigationTask: ITask;
	private var mDisableSequencesNavigationTask: ITask;
	private var mUnselectButtonsTask: ITask;
	
	private var mLinearSequence: TaskSequence;
	private var mBackwardsSequence: TaskSequence;
	private var mZigzagSequence: TaskSequence;
	// ComplexSequence executes complicated, aschyncrons tasks and have to be TaskManager.
	private var mComplexSequence: TaskManager;	
	
	public function InterruptibleSection() 
	{
		super();
		
		// Get the instances from the scene.		
		
		// Use "getComponentByPath()" to obtain a reference to the buttons,
		// because their movie clips are nested in the "SequencesNavigation" movie clip 
		// and we can't get to it using getComponent().
		mLinearSequenceButton = getComponentByPath(["SequencesNavigation","btnLinearSequence"]);
		mBackwardsButton = getComponentByPath(["SequencesNavigation","btnBackwards"]);
		mZigZagSequenceButton = getComponentByPath(["SequencesNavigation", "btnZigZagSequence"]);	
		mComplexSequenceButton = getComponentByPath(["SequencesNavigation", "btnComplexSequence"]);		
	}
	
	public function initUI()
	{
		super.initUI();
		
		// Configure sequences navigation menu.
		configureButtons();		
		
		// Create task that will unselect all the items of the sequences navigation menu.
		// This task must be included in the final of all sequences. This is necessary, because 
		// otherwise the sequences that have been executed stay selected.
		mUnselectButtonsTask = ExecuteMethodTask.create(this, unselectButtons);
		
		// Prepare the sequences.	
		
		// Linear sequence is simple sequence that execute the animations one by one.  	
		mLinearSequence = prepareLinearSequence();
		// Backwards sequence is simple sequence that execute the animations backwards.
		mBackwardsSequence = prepareBackwardsSequence();
		// Zigzag sequence is simple sequence that execute the animations in the order : 
		// TitleAnim,CupAnim,MailAnim,EggsAnim,LogoAnim.
		mZigzagSequence = prepareZigzagSequence();
		// Complex sequence executes the animations asynchronously. The order is : 
		// TitleAnim,MailAnim starts simultaneously, LogoAnim starts on complete of TitleAnim and MailAnim, 
		// CupAnim starts on complete of LogoAnim,
		// CupAnim - on complete of LogoAnim and EggsAnim in the middle of the CupAnim. 
		mComplexSequence = prepareComplexSequence();
		
		// Initialization sequence		
		// Using the CommonSection initialization sequence.
		
		// Activating sequence		
		// Using the CommonSection activating sequence.
		
		// Open sequence		
		// Using the CommonSection open sequence.
		
		// Close sequence		
		// Using the CommonSection close sequence. 
	}
	
	private function configureButtons(): Void
	{
		mLinearSequenceButton.addEventListener("click", Delegate.create(this, onLinearSequenceButtonClick));
		mBackwardsButton.addEventListener("click", Delegate.create(this, onBackwardsButtonClick));
		mZigZagSequenceButton.addEventListener("click", Delegate.create(this, onZigZagSequenceButtonClick));
		mComplexSequenceButton.addEventListener("click", Delegate.create(this, onComplexSequenceButtonClick));	
	}
	
	private function prepareLinearSequence() : TaskSequence
	{
		var linearSequence : TaskSequence = new TaskSequence();
		linearSequence.addTask(mTitleAnim);
		linearSequence.addTask(mMailAnim);
		linearSequence.addTask(mLogoAnim);
		linearSequence.addTask(mCupAnim);
		linearSequence.addTask(mEggsAnim);
		linearSequence.addTask(mUnselectButtonsTask);
	
		return linearSequence;	
	}
	
	private function prepareBackwardsSequence() : TaskSequence
	{
		var backToFrontSequence : TaskSequence = new TaskSequence();
		backToFrontSequence.addTask(mEggsAnim);
		backToFrontSequence.addTask(mCupAnim);
		backToFrontSequence.addTask(mLogoAnim);
		backToFrontSequence.addTask(mMailAnim);
		backToFrontSequence.addTask(mTitleAnim);	
		backToFrontSequence.addTask(mUnselectButtonsTask);	
	
		return backToFrontSequence;	
	}
	
	private function prepareZigzagSequence() : TaskSequence
	{
		var zigzagSequence : TaskSequence = new TaskSequence();
		zigzagSequence.addTask(mTitleAnim);
		zigzagSequence.addTask(mCupAnim);
		zigzagSequence.addTask(mMailAnim);
		zigzagSequence.addTask(mEggsAnim);
		zigzagSequence.addTask(mLogoAnim);
		zigzagSequence.addTask(mUnselectButtonsTask);		
	
		return zigzagSequence;	
	}
	
	private function prepareComplexSequence() : TaskManager
	{
		// Add cue point at frame 10. When the animation "mCupAnim" reaches to frame 10
		// it will dispatch event "middle".
		mCupAnim.addCuePoint(10, "middle");	
		
		// This is the precondition, which is necessary for the "mEggsAnim" to be executed.
		// The "mEggsAnim" starts when the "mCupAnim" dispatch the event "middle".
		var eggsAnimPrecondition : EventDescriptor = new EventDescriptor(mCupAnim, "middle"); 
		
		// Initialize the Task Manager as unaccepting (false in the constructor), 
		// because don't need to listen for the events, before start.
		// Instantiate task manager. Add all tasks with desired dependencies.
		var mComplexSequenceTaskManager: TaskManager = new TaskManager(false);
		mComplexSequenceTaskManager.addStartingTasks([mTitleAnim, mMailAnim]);
		mComplexSequenceTaskManager.addTaskWithPredecessors(mLogoAnim,[mTitleAnim,mMailAnim]);
		mComplexSequenceTaskManager.addTaskWithPredecessor(mCupAnim, mLogoAnim);
		mComplexSequenceTaskManager.addTaskWithPrecondition(mEggsAnim, eggsAnimPrecondition);
		mComplexSequenceTaskManager.addTaskWithPredecessor(mUnselectButtonsTask, mEggsAnim);
		mComplexSequenceTaskManager.setFinalTask(mUnselectButtonsTask);
				
		return mComplexSequenceTaskManager;
	}
	 
	// In this section the sequences must be interruptible. That gives the opportunity to start the new sequence,
	// although the previous isn't completed.  
	private function interruptSequence() : Void
	{
		// Interrupt the current sequence.
		mCurrentSequence.interrupt();
		// After the sequence have been interrupted, all the animations must be hided.
		mTitleAnim.hide();
		mMailAnim.hide();
		mLogoAnim.hide();
		mCupAnim.hide();
		mEggsAnim.hide();
	
	}

	private function onLinearSequenceButtonClick()
	{
		interruptSequence();
		mCurrentSequence = mLinearSequence;
						
		mLinearSequence.start();
	}
	
	private function onBackwardsButtonClick()
	{
		interruptSequence();
		mCurrentSequence = mBackwardsSequence;		
		
		mBackwardsSequence.start();
	}
	
	private function onZigZagSequenceButtonClick()
	{
		interruptSequence();
		mCurrentSequence = mZigzagSequence;
		
		mZigzagSequence.start();
	}
	
	private function onComplexSequenceButtonClick()
	{
		interruptSequence();
		mCurrentSequence = mComplexSequence;
					
		// Before starting the Task Manger, first must set every task manager item acceptable for all of the 
	    // preconditions that are associated with it.
		mComplexSequence.acceptAll();
		mComplexSequence.start();
	}
	
	private function unselectButtons () : Void	 
	{
		mLinearSequenceButton.unselect();
		mBackwardsButton.unselect();
		mZigZagSequenceButton.unselect();
		mComplexSequenceButton.unselect();
	}
}